package cn.assumejson.pro_netty.core;

import cn.assumejson.pro_netty.netty.client.asyn.RequestFuture;
import cn.assumejson.pro_netty.netty.client.asyn.Response;
import cn.assumejson.pro_netty.utils.GsonUtil;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 缓存 Netty 服务的容器
 *
 * @author by gang.Li 2022/3/12 14:40
 */
public class Mediator {
    public static Map<String, MethodBean> methodBeans;

    static {
        methodBeans = new HashMap<>();
    }

    /**
     * 请求分发
     *
     * @param requestFuture requestFuture
     * @return Response
     */
    public static Response process(RequestFuture requestFuture) {
        // 构建响应对象
        Response response = new Response();

        String path = requestFuture.getPath();
        // 根据请求路径从缓存中获取请求路径对应的bean 和method
        MethodBean methodBean = methodBeans.get(path);
        if (methodBean != null) {
            Method method = methodBean.getMethod();
            Object bean = methodBean.getBean();

            // 获取请求数据，进行数据封装
            Object body = requestFuture.getRequest();

            // 获取方法的请求参数
            // TODO 目前只支持一个参数
            Class<?>[] parameterTypes = method.getParameterTypes();
            Class<?> parameterType = parameterTypes[0];
            // 对参数进行反序列化
            try {
                Object result = method.invoke(bean, getDeserialized(body, parameterType));
                response.setResult(result);
            } catch (IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        response.setId(requestFuture.getId());
        return response;
    }

    /**
     * 获取反序列化结果集
     *
     * @param body          请求体
     * @param parameterType 方法入参类型
     */
    private static Object getDeserialized(Object body, Class<?> parameterType) {
        Object param = null;
        if (parameterType.isAssignableFrom(List.class)) {
            param =  GsonUtil.gson.toJson(GsonUtil.gson.toJson(body), parameterType);
//            param = JSONArray.parseArray(JSONArray.toJSONString(body), parameterType);
        } else if (parameterType.getName().equals(String.class.getName())) {
            param = body;
        } else {
//            param = JSONObject.parseObject(JSONObject.toJSONString(body), parameterType);
            param =  GsonUtil.gson.toJson(GsonUtil.gson.toJson(body), parameterType);
        }
        return param;
    }

    public static class MethodBean {
        private Object bean;
        private Method method;

        public Object getBean() {
            return bean;
        }

        public void setBean(Object bean) {
            this.bean = bean;
        }

        public Method getMethod() {
            return method;
        }

        public void setMethod(Method method) {
            this.method = method;
        }
    }
}
